package com.ehotting.edsta.circuitDesign.gen;

import com.ehotting.edsta.circuitDesign.bean.AllMapBean;
import com.ehotting.edsta.circuitDesign.bean.CircuitElementBean;
import com.ehotting.edsta.circuitDesign.bean.CircuitGroupBean;
import com.ehotting.edsta.circuitDesign.bean.ProCodeName;
import com.ehotting.edsta.circuitDesign.bean.request.RequestCodeExecute;
import com.ehotting.edsta.circuitDesign.domain.EsElement;
import com.ehotting.edsta.circuitDesign.enums.CircuitTypeEnum;
import com.ehotting.edsta.circuitDesign.enums.CodeDataTypeEnum;
import com.ehotting.edsta.circuitDesign.gen.element.ElementScriptEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class ElementEngine {

    private static final Logger logger = LoggerFactory.getLogger(ElementEngine.class);

    @Autowired
    private ElementScriptEngine elementScriptEngine;

    public void invoke(List<CircuitGroupBean> circuitGroupList, Map<String,Object> context,AllMapBean contextMap){
        logger.info("Start invoke.");
        for(CircuitGroupBean circuitGroup : circuitGroupList){
            Collection<CircuitElementBean> collection =  circuitGroup.values();
            invoke(collection,  context,contextMap);
        }
        logger.info("finish invoke.");
    }

    private void invoke(Collection<CircuitElementBean> circuitElementList, Map<String,Object> context,AllMapBean contextMap){
        for(CircuitElementBean circuitElement : circuitElementList){
            invokeAnalogueData( circuitElement, context,  contextMap);
        }
    }

    private void invokeAnalogueData(CircuitElementBean circuitElement,Map<String,Object> context, AllMapBean contextMap){
        List<RequestCodeExecute.InputChannel> channelList = circuitElement.getChannelList();
        if(channelList.size()>0){
            // TODO: 2023/11/16 使用多线程优化
            for(int index = 0;index<circuitElement.getCount();index++){
                Integer channelNum = circuitElement.getChannelNum();
                Integer startIndex = index * channelNum;
                Integer endIndex = (index+1) * channelNum ;
                if(endIndex > channelList.size()){
                    endIndex = channelList.size();
                }
                List<RequestCodeExecute.InputChannel> subChannelList = channelList.subList(startIndex,endIndex);
                if(subChannelList.size()>0 && subChannelList.get(0) instanceof RequestCodeExecute.AnalogueData) {
                    AllMapBean contextMapTemp = getAnalogueAllMapBean(subChannelList, contextMap.clone());
                    Map<String, EsElement> elementMap = elementScriptEngine.invoke(circuitElement.getCircuit().getId(), context, contextMapTemp);
                    circuitElement.getElementList().add(elementMap);
                }
            }
        }else{
            Map<String, EsElement> elementMap = elementScriptEngine.invoke(circuitElement.getCircuit().getId(), context, contextMap);
            circuitElement.getElementList().add(elementMap);
        }
    }

    private AllMapBean getAnalogueAllMapBean(List<RequestCodeExecute.InputChannel> subChannelList, AllMapBean contextMap){
        List<RequestCodeExecute.AnalogueData> analogueChannelList = subChannelList
                .stream()
                .map(t->{return (RequestCodeExecute.AnalogueData)t; })
                .collect(Collectors.toList());
        StringBuffer inputMaxDataRange = new StringBuffer();
        for(RequestCodeExecute.AnalogueData ch:analogueChannelList){
            if(ch.getMaxdatarange() != null){
                if(inputMaxDataRange.length() == 0){
                    inputMaxDataRange.append(ch.getMaxdatarange());
                }else {
                    inputMaxDataRange.append(",").append(ch.getMaxdatarange());
                }
            }
        }

        Map<String, Object> map = contextMap.get(CircuitTypeEnum.SENSOR, CodeDataTypeEnum.PROP);
        if(map==null){
            map = new HashMap();
        }
        map.put(ProCodeName.Input_Max_Data_Range,inputMaxDataRange.toString());
        contextMap.put(CircuitTypeEnum.SENSOR, CodeDataTypeEnum.PROP,map);
        return contextMap;
    }
}